import DialogConstructor from "../dialog";
import { h, render, VNode, ComponentInternalInstance } from "vue";
import { MessageBoxOptions, OptionsResult } from "./messageBox.type";
import { t } from "../../locale";
import { CommonUtil } from "../../utils";
import PromptForm from "./promptForm.vue";
const ICON_CLASS = {
  warning: "bi bi-exclamation-triangle-fill",
  info: "bi bi-info-circle-fill",
  danger: "bi bi-x-circle-fill",
  success: "bi bi-check-circle-fill",
};
function initMessageBox(
  options: MessageBoxOptions & { onClosed?: () => void }
): ComponentInternalInstance {
  let container: HTMLElement | null = document.createElement("div");
  options.modelValue = true;
  options.onClosed = () => {
    container && render(null, container);
    container = null;
  };
  const vnode: VNode = h(DialogConstructor, options);
  render(vnode, container);
  if (container.firstElementChild) {
    document.body.appendChild(container.firstElementChild);
  }
  return vnode.component as ComponentInternalInstance;
}
function getOptions(
  mes: string | VNode,
  title: string,
  options?: MessageBoxOptions
): OptionsResult {
  options = options || {};
  options.title = title;
  options.content = mes;
  if (options.type) {
    options.bodyIcon = `<i class="${ICON_CLASS[options.type]} text-${
      options.type
    }" style='font-size:1.5rem'></i>`;
  }
  options = Object.assign(
    {
      size: "sm",
      centered: false,
      static: true,
      okHandler: null,
      okText: t("vb.global.ok"),
      okTheme: "primary",
      okClose: true,
      cancelHandler: null,
      cancelText: t("vb.global.cancel"),
      cancelTheme: "secondary",
      cancelClose: true,
      bodyIcon: "",
      closable: false,
    },
    options
  );
  return {
    dialog: {
      ...CommonUtil.getSubObj(options, [
        "title",
        "content",
        "size",
        "centered",
        "static",
        "bodyIcon",
        "closable",
      ]),
    },
    button: {
      ...CommonUtil.getSubObj(options, [
        "okHandler",
        "okText",
        "okTheme",
        "okClose",
        "cancelHandler",
        "cancelText",
        "cancelTheme",
        "cancelClose",
      ]),
    },
  };
}

const MessageBox = {
  alert(mes: string | VNode, title: string, options?: MessageBoxOptions) {
    const { dialog, button } = getOptions(mes, title, options);
    const instance: any = initMessageBox({
      buttons: [
        {
          text: button.okText,
          handler: button.okHandler,
          theme: button.okTheme,
          close: button.okClose,
        },
      ],
      ...dialog,
    });
    return instance.proxy;
  },
  confirm(mes: string | VNode, title: string, options?: MessageBoxOptions) {
    const { dialog, button } = getOptions(mes, title, options);
    const instance: any = initMessageBox({
      buttons: [
        {
          text: button.cancelText,
          handler: button.cancelHandler,
          theme: button.cancelTheme,
          close: button.cancelClose,
        },
        {
          text: button.okText,
          handler: button.okHandler,
          theme: button.okTheme,
          close: button.okClose,
        },
      ],
      ...dialog,
    });
    return instance.proxy;
  },
  prompt(mes: string | VNode, title: string, options?: MessageBoxOptions) {
    let promptFormInstance: any = null;
    const promptFormVNode = h(PromptForm, {
      label: mes,
      reg: options ? options.inputReg : null,
      invalidMes: options ? options.invalidMes : null,
      onVnodeMounted(e: VNode) {
        promptFormInstance = e.component;
      },
      onVnodeUnmounted() {
        promptFormInstance = null;
      },
    });
    const { dialog, button } = getOptions(promptFormVNode, title, options);
    const instance: any = initMessageBox({
      buttons: [
        {
          text: button.cancelText,
          handler: button.cancelHandler,
          theme: button.cancelTheme,
          close: button.cancelClose,
        },
        {
          text: button.okText,
          handler(btn: any) {
            if (promptFormInstance && promptFormInstance.proxy) {
              const value = promptFormInstance.proxy.doValid();
              if (value === false) {
                return false;
              }
              button.okHandler && button.okHandler({ value, btn });
            }
          },
          theme: button.okTheme,
          close: button.okClose,
        },
      ],
      ...dialog,
    });
    return instance.proxy;
  },
};
export default MessageBox;
